#include"myThread.hpp"
#include"Task.hpp"
#include"Mutex.hpp"

struct Data //我们还是拿前面的计算任务来举例
{
    //每个线程需要知道自己的名字以及任务队列
    Data(std::string name ,std::queue<Task>* q,pthread_mutex_t * mutex,pthread_cond_t * cond ) //每个线程还需要拿到所和条件变量
    :_name(name),_q(q),_mutex(mutex),_cond(cond)
    {}

    std::string _name;
    std::queue<Task>* _q;
    pthread_mutex_t * _mutex;
    pthread_cond_t * _cond; 
};


//线程需要执行的方法
void* start_routine(void* arg)
{
    Data* pdata= (Data*)arg;
    std::string name =pdata->_name;
    std::queue<Task>* pq=pdata->_q; 
    pthread_mutex_t * pmutex = pdata->_mutex;
    pthread_cond_t * pcond = pdata->_cond; 
    //不管怎么样，刚运行肯定还没任务，直接去等待
    while(1)
    {
        Task t;
        Mutex m(pmutex);
        while(pq->empty())
        pthread_cond_wait(pcond,pmutex);

        t=pq->front();
        pq->pop();
        std::cout<<name<<"拿到了一个任务，执行结果:"<<t()<<std::endl;
        usleep(100000);
    } 


}



class ThreadPool
{
public:
typedef std::function<void*(void*)> func_t;
private:    
    //构造
    ThreadPool(size_t num = 5) //只需要传线程个数
    :_thread_count(num)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        _threads.resize(num);
        for(int i=0;i<num;++i) //将现场的对象创建好
        {
            _threads[i]=new Thread();
        }
    }
public:
    ThreadPool* getsingleton() //获取单例
    {
        if(ptp==nullptr)
        {
            Mutex(&stamutex);
            if(ptp!=nullptr)
            ptp=new ThreadPool();
        }
        return ptp;
    }    
    void start() //创建线程
    {
        for(auto& th:_threads)
        {
            Data* data=new Data(th->getname(),&_q , &_mutex,&_cond);
            th->start(start_routine,(void*)data);
        }
    }
    bool empty()
    {
        return _q.empty();
    }
    void push(const Task&t)
    {
        Mutex m(&_mutex);
        _q.push(t);
        //唤醒线程来拿任务
        pthread_cond_signal(&_cond);
    }

    void pop(Task*pt)
    {
        Mutex t(&_mutex);
        *pt=_q.front();
        _q.pop();
    }


private:
    std::queue<Task> _q;
    std::vector<Thread*> _threads;
    size_t _thread_count;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    static ThreadPool*ptp;
    static pthread_mutex_t stamutex;
};

ThreadPool* ThreadPool::ptp =nullptr;
Thread_mutex_t ThreadPool::stamutex =PTHREAD_MUTEX_INITIALIZER;


//正常线程池
// class ThreadPool
// {
// public:
// typedef std::function<void*(void*)> func_t;
//     //构造
//     ThreadPool(size_t num = 5) //只需要传线程个数
//     :_thread_count(num)
//     {
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_cond,nullptr);
//         _threads.resize(num);
//         for(int i=0;i<num;++i) //将现场的对象创建好
//         {
//             _threads[i]=new Thread();
//         }
//     }
//     void start() //创建线程
//     {
//         for(auto& th:_threads)
//         {
//             Data* data=new Data(th->getname(),&_q , &_mutex,&_cond);
//             th->start(start_routine,(void*)data);
//         }
//     }
//     void push(const Task&t)
//     {
//         Mutex m(&_mutex);
//         _q.push(t);
//         //唤醒线程来拿任务
//         pthread_cond_signal(&_cond);
//     }

//     void pop(Task*pt)
//     {
//         Mutex t(&_mutex);
//         *pt=_q.front();
//         _q.pop();
//     }


// private:
//     std::queue<Task> _q;
//     std::vector<Thread*> _threads;
//     size_t _thread_count;
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;
// };